<template>
  <div>
    <el-upload
      ref="el"
      style="width: 100%"
      v-bind="$props.props"
      action=""
      :on-exceed="handleOnExceed"
      :before-upload="handleBeforeUpload"
      :http-request="handleHttpRequest"
      :file-list="computedFileList"
      :before-remove="handleBeforeRemove"
      :show-file-list="false"
      list-type="text"
      v-on="$listeners"
    >
      <el-button
        v-if="listType === 'picture' || listType === 'picture-card'"
        type="primary"
      >
        <div class="upload-img-button upload-button">
          <div class="icon">
            <i class="iconfont icon-shangchuan upload-icon" />
          </div>
          <div class="content">
            <div class="title">
              {{ uploadImgTitle }}
            </div>
            <div class="desc">
              {{ uploadImgDesc }}
            </div>
          </div>
        </div>
      </el-button>
      <div
        v-else
        class="upload-button upload-file-button"
      >
        <div class="icon">
          <i class="iconfont icon-wenjian upload-icon" />
        </div>
        <div class="content">
          <div class="title">
            {{ uploadFileTitle }}
          </div>
          <div class="desc">
            {{ uploadFileDesc }}
          </div>
        </div>
      </div>
      <div
        slot="tip"
        class="el-upload__tip"
      >
        {{ uploadTip }}
      </div>
    </el-upload>
    <div
      v-if="listType === 'picture' || listType === 'picture-card'"
      class="erp-form-upload-preview"
    >
      <div
        v-for="(item, index) in computedFileList"
        :key="index"
        class="erp-form-upload-preview-item"
        @click.stop="handleShowViewer(item)"
      >
        <div class="img-wrap">
          <div class="img">
            <el-image
              class="img-item"
              :src="item.url"
              :lazy="lazy"
              fit="cover"
              width="100%"
              height="100%"
            />
          </div>
          <div class="modal">
            <div class="triangle" />
            <i class="iconfont icon-dui triangle-icon" />
          </div>
          <div class="modal-bg" />
          <div
            class="modal-wrong"
            @click.stop="deleteImg(item, index)"
          >
            <div class="triangle wrong" />
            <i class="iconfont icon-wrong triangle-icon" />
          </div>
        </div>
      </div>
    </div>
    <div
      v-else
      class="erp-form-upload-file-list"
    >
      <div
        v-for="(item, index) in computedFileList"
        :key="index"
        class="erp-form-upload-file-list-item"
        @click="previewFile(item)"
      >
        <div class="icon">
          <i
            v-if="fileExt(item.url) === 'doc' || fileExt(item.url) === 'docx'"
            class="iconfont icon-gongchenglianxidanshenpiiconfujianword icon-font word"
          />
          <i
            v-else-if="fileExt(item.url) === 'xls' || fileExt(item.url) === 'xlsx'"
            class="iconfont icon-excel icon-font excel"
          />
          <i
            v-else-if="fileExt(item.url) === 'ppt' || fileExt(item.url) === 'pptx'"
            class="iconfont icon-ppt icon-font ppt"
          />
          <i
            v-else-if="fileExt(item.url) === 'pdf'"
            class="iconfont icon-pdf icon-font pdf"
          />
          <i
            v-else
            class="iconfont icon-fileweizhi icon-font unknown"
          />
        </div>
        <div class="content">
          <div class="title">
            附件{{ (index + 1) }}.{{ fileExt(item.url) }}
          </div>
        </div>
        <div class="triangle">
          <div class="triangle-box">
            <div class="triangle-bg" />
            <div class="triangle-icon">
              <i class="iconfont icon-dui icon" />
            </div>
          </div>
        </div>
        <div class="triangle-box-wrong">
          <div
            class="triangle-box"
            @click.stop="deleteImg(item, index)"
          >
            <div class="triangle-bg wrong" />
            <div class="triangle-icon">
              <i class="iconfont icon-wrong icon" />
            </div>
          </div>
        </div>
      </div>
    </div>
    <el-image-viewer
      v-if="showViewer"
      :on-close="handleClosePreview"
      :url-list="[currentImg]"
    />
  </div>
</template>

<script>
import Vue from 'vue';
import {Upload, Image} from "element-ui";
import {toast} from "@/utils";
import {loadingToast} from "../../../utils";
import {uploadImg} from "@/api/file";
import ElImageViewer from 'element-ui/packages/image/src/image-viewer';
import {converBitSize} from "../../../utils";

Vue.use(Upload);
Vue.use(Image);

const extra = {
  // 文件最大上传大小（单位：B）默认2MB
  maxSize: 2 * 1024 * 1024,
  // 图片是否懒加载显示, 默认true
  lazy: true
};

/**
 * 文件上传组件
 * @author maolin
 */
export default {
  name: "ErpFormUpload",
  components: {
    ElImageViewer
  },
  props: {
    /**
     * 标题
     * @public
     */
    title: {
      type: String,
      default: '',
    },
    /**
     * 字段
     * @public
     */
    field: {
      type: String,
      default: ''
    },
    /**
     * 值，文件路径
     * @public
     */
    value: {
      default () {
        return '';
      }
    },
    /**
     * 属性
     * @public
     */
    props: {
      type: Object,
      default () {
        return {
        };
      }
    },
    /**
     * 额外配置
     * ```js
     * return {
  // 文件最大上传大小（单位：B）默认2MB
  maxSize: 2 * 1024 * 1024,
  // 图片是否懒加载显示, 默认true
  lazy: true
}
     * ```
     * @public
     */
    extra: {
      type: Object,
      default () {
        return extra;
      }
    },
  },
  data () {
    return {
      currentImg: "",
      showViewer: false,
      uploadImgTitle: "上传图片",
      uploadFileTitle: "上传文件",
    };
  },
  computed: {
    lazy () {
      return !(this.extra && this.extra.lazy === false);
    },
    limit () {
      return this.props && this.props.limit ? this.props.limit : 1;
    },
    fileExt () {
      return function (url) {
        let ext = null;
        if (url) {
          let index = url.lastIndexOf('.');
          if (index > -1) {
            ext = url.substring(index + 1);
          }
        }
        return ext;
      };
    },
    listType () {
      return this.props && this.props.listType ? this.props.listType : 'text';
    },
    previewSrcList () {
      let fileList = this.computedFileList;
      let array = [];
      if (fileList && fileList.length > 0) {
        for (let i in fileList) {
          array.push(fileList[i].url);
        }
      }
      return array;
    },
    computedExtra () {
      let extraProp = this.extra;
      let obj = {};
      for (let i in extra) {
        if (extraProp[i] !== undefined) {
          obj[i] = extraProp[i];
        } else {
          obj[i] = extra[i];
        }
      }
      return obj;
    },
    uploadImgDesc () {
      return "大小不超过" + this.bitToKBit(this.computedExtra.maxSize);
    },
    uploadFileDesc () {
      return "大小不超过" + this.bitToKBit(this.computedExtra.maxSize);
    },
    bitToKBit () {
      return function (bit) {
        if(bit) {
          return converBitSize(bit);
        }
        return null;
      };
    },
    computedFileList: {
      get () {
        let value = this.value;
        let array = [];
        if (value) {
          array = value.split(',');
        }
        let fileList = [];
        if (array && array.length > 0) {
          for (let i in array) {
            fileList.push({
              url: array[i],
              name: array[i]
            });
          }
        }
        return fileList;
      },
      set (fileList) {
        let str = '';
        let array = [];
        if (fileList && fileList.length > 0) {
          for (let i in fileList) {
            array.push(fileList[i].url);
          }
        }
        if (array && array.length > 0) {
          str = array.join(',');
        }
        this.$emit('value-change', str);
      }
    },
    uploadTip () {
      if (this.extra && this.extra.uploadTip) {
        return this.extra.uploadTip;
      }
      return '';
    }
  },
  mounted() {
  },
  methods: {
    /**
     * 预览文件
     * @private
     */
    previewFile (item) {
      window.open(item.url);
    },
    /**
     * 删除文件
     * @private
     */
    deleteImg (item, index) {
      let fileList = this.computedFileList;
      fileList.splice(index, 1);
      this.computedFileList = fileList;
    },
    /**
     * 预览图片
     * @private
     */
    handleShowViewer (item) {
      this.showViewer = true;
      this.currentImg = item.url;
    },
    /**
     *
     * 文件超出个数限制时的钩子，详情见element-ui的[Upload](https://element.eleme.cn/2.13/#/zh-CN/component/upload#attribute)
     * @private
     */
    handleOnExceed (fileList) {
      const fileListLength = fileList.length;
      if (this.props['on-exceed']) {
        eval(this.props['on-exceed']);
      } else if (fileListLength === 1) {
        let file = fileList[0];
        let formdata = new FormData();
        formdata.append('file', file);
        let loading = loadingToast();
        uploadImg(formdata)
          .then(res => {
            this.computedFileList = [{
              name: res.data.path,
              url: res.data.path,
            }];
            loading.close();
          })
          .catch(() => {
            loading.close();
          });
        return false;
      } else {
        toast({
          message: '文件个数不能超出' + this.limit + '个',
          type: 'error'
        });
        return false;
      }
    },
    /**
     * 关闭图片预览
     * @private
     */
    handleClosePreview () {
      this.showViewer = false;
    },
    /**
     * 上传之前判断是否超出大小限制
     * @private
     */
    handleBeforeUpload (file) {
      if (this.props['before-upload']) {
        eval(this.props['before-upload']);
      } else {
        const isLt = file.size <= this.computedExtra.maxSize;
        if (!isLt) {
          toast({
            message: '上传文件大小不能超过 ' + this.bitToKBit(this.computedExtra.maxSize),
            type: 'error'
          });
          return false;
        }
        return true;
      }
    },
    /**
     * 移除某一项已上传文件
     * @private
     */
    handleBeforeRemove (file, fileList) {
      if (this.props['before-remove']) {
        eval(this.props['before-remove']);
      } else {
        let url = file.url;
        let index = -1;
        let fileLists = this.computedFileList;
        if (fileLists && fileLists.length > 0) {
          for (let i in fileLists) {
            if (url == fileLists[i].url) {
              index = i;
              break;
            }
          }
        }
        if (index > -1) {
          let computedFileList = this.computedFileList;
          computedFileList.splice(index, 1);
          this.computedFileList = computedFileList;
        }
      }
    },
    /**
     * 上传请求
     * @private
     */
    handleHttpRequest (data) {
      let file = data.file;
      let formdata = new FormData();
      formdata.append('file', file);
      uploadImg(formdata)
        .then(res => {
          let data = this.computedFileList;
          data.push({
            name: res.data.path,
            url: res.data.path,
          });
          this.computedFileList = data;
        });
      return false;
    }

  }
};
</script>

<style lang="scss" scoped>
    $primaryColor: var(--primary-color);
    ::v-deep{
        .el-image-viewer__close{
            background-color: #000;
            color: #fff;
        }
    }
    .upload-button{
        display: flex;
        flex-wrap: nowrap;
        &.upload-file-button{
            border: 1px solid $primaryColor;
            border-radius: 2px;
            padding: 8px 15px;
            background-color: #D6EEFF;
            .icon{
                .upload-icon{
                    font-size:36px;
                    color: $primaryColor;
                }
            }
            .content{
                .title{
                    color: #333;
                }
                .desc{
                    color: #838C9D;
                }
            }
        }
        .icon{
            width: 50px;
            height: 40px;
            line-height: 40px;
            .upload-icon{
                font-size:40px;
            }
        }
        .content{
            width: calc(100% - 50px);
            margin-left: 10px;
            .title{
                font-weight: bold;
                text-align: left;
                height: 25px;
                font-size: 16px;
                line-height: 25px;
            }
            .desc{
                font-size: 12px;
                line-height: 15px;
            }
        }
    }
    .erp-form-upload-preview{
        display: flex;
        flex-wrap: wrap;
        .erp-form-upload-preview-item{
            width: 70px;
            height: 70px;
            margin-right: 12px;
            margin-bottom: 12px;
            overflow: hidden;
            cursor: pointer;
            box-shadow: 0 0 5px #ccc;
            .img-wrap{
                width: 70px;
                height: 70px;
                position: relative;
                .img{
                    .img-item{
                        width: 70px;
                        height: 70px;
                    }
                }
                .modal, .modal-wrong{
                    position: absolute;
                    width: 25px;
                    height: 25px;
                    top: 0;
                    right:0;
                    z-index: 100;
                    .triangle{
                        position: absolute;
                        top: 0;
                        right: 0;
                        width: 0;
                        height: 0;
                        border-top: 25px solid #22DA81;
                        border-left: 25px solid transparent;
                        &.wrong{
                            border-top: 25px solid #F46262;
                        }
                    }
                    .triangle-icon{
                        position: absolute;
                        height: 12px;
                        line-height: 12px;
                        top: 2px;
                        right: 2px;
                        font-size: 12px;
                        color: #fff;
                    }
                }
                .modal-wrong{
                    display: none;

                }
                .modal-bg{
                    display: none;
                    position: absolute;
                    top: 0;
                    left:0;
                    width: 70px;
                    height: 70px;
                    background-color: rgba(0,0,0,0.5);
                    z-index: 90;
                }
            }
            &:hover{
                .modal-wrong {
                    display: block;
                }
                .modal{
                    display: none;
                }
                .modal-bg{
                    display: block;
                }
            }
        }

    }
    .erp-form-upload-file-list {
        max-width: 300px;
        .erp-form-upload-file-list-item{
            display: flex;
            flex-wrap: nowrap;
            margin-bottom: 12px;
            background-color: #E9EEF2;
            position: relative;
            border-radius: 2px;
            padding: 10px;
            cursor: pointer;
            box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
            &:hover{
                background-color: #fff;
                .triangle{
                    display: none;
                }
                .triangle-box-wrong{
                    display: block;
                }
            }
            .icon{
                width: 48px;
                height: 48px;
                .icon-font{
                    font-size: 48px;
                    line-height: 48px;
                    &.word {
                        color: #0D91FE;
                    }
                    &.excel{
                        color: #34D3B7;
                    }
                    &.ppt{
                        color: #F46262;
                    }
                    &.pdf{
                        color: #f56f46;
                    }
                    &.unknown {
                        color: #ccc;
                    }
                }
            }
            .content{
                width: calc(100% - 60px);
                margin-left: 12px;
                padding: 4px;
                .title{
                    height: 20px;
                    line-height: 20px;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                    font-size: 14px;
                    color: #666;
                }
            }
            .triangle,.triangle-box-wrong{
                width: 25px;
                height: 25px;
                position: absolute;
                top: 0;
                right: 0;
                .triangle-box{
                    position: relative;
                    left: 0;
                    top: 0;
                    width: 100%;
                    height: 100%;
                    .triangle-bg{
                        position: absolute;
                        top: 0;
                        right: 0;
                        width: 0;
                        height: 0;
                        border-top: 25px solid #22DA81;
                        border-left: 25px solid transparent;
                        &.wrong{
                            border-top: 25px solid #F46262;
                        }
                    }
                    .triangle-icon{
                        height: 12px;
                        line-height: 12px;
                        position: absolute;
                        top: 2px;
                        right: 2px;
                        color: #fff;
                        .icon{
                            font-size: 12px;
                        }
                    }
                }

            }
            .triangle-box-wrong{
                display: none;
            }
        }
    }
</style>
